from django.core.paginator import Paginator, EmptyPage
from django.db import transaction
import json
from _decimal import Decimal
import logging

logger = logging.getLogger('django')

from django import http
from django.shortcuts import render

# Create your views here.
from django.utils import timezone
from django.views import View
from django_redis import get_redis_connection

from goods.models import SKU
from meiduo_mall.utils.response_code import RETCODE
from meiduo_mall.utils.views import LoginRequiredMinxin, LoginRequiredJSONMixin
from orders.models import OrderInfo, OrderGoods
from users.models import Address
class UserOrderInfoView(LoginRequiredMinxin,View):
    '''我的订单'''
    def get(self,request,page_num):
        '''提供我的订单页面'''
        user=request.user
        #查询订单
        orders=user.orderinfo_set.all().order_by('-create_time')
        #遍历所有订单
        for  order in orders:
            #绑定订单状态
            order.status_name=OrderInfo.ORDER_STATUS_CHOICES[order.status-1][1]
            order.pay_method_name=OrderInfo.PAY_METHOD_CHOICES[order.pay_method-1][1]

            #获取该订单的所有行
            order_goods=order.skus.all()

            order.sku_list=[]
            #5.遍历所有行
            for order_good in order_goods:
                #6.获取行中的商品-----》sku每一条商品
                sku=order_good.sku
                #7.获取行中的数量-----》sku
                sku.count=order_good.count
                #8.计算sku的总价
                sku.amount=sku.price* sku.count
                #9.添加到订单的列表中
                order.sku_list.append(sku)
        page_num=int(page_num)
        try:
            paginator=Paginator(orders,1)
            page_orders=paginator.page(page_num)
            total_page=paginator.num_pages
        except EmptyPage:
            return  http.HttpResponseForbidden('page_id出错')
        context={
            "page_orders": page_orders,
            'total_page': total_page,
            'page_num': page_num,
        }

        return render(request,'user_center_order.html',context)






class OrderSuccessView(LoginRequiredMinxin,View):
    '''提交订单成功'''
    def get(self,request):
        order_id=request.GET.get('order_id')
        payment_amount=request.GET.get('payment_amount')
        pay_method=request.GET.get('pay_method')

        context={
            'order_id':order_id,
            'payment_amount':payment_amount,
            'pay_method':pay_method

        }
        return render(request,'order_success.html',context)


class OrderCommitView(LoginRequiredJSONMixin, View):
    def post(self, request):
        '''
        保存订单信息
        :param request:
        :return:
        '''
        # 1.接收参数
        json_dict = json.loads(request.body.decode())
        address_id = json_dict.get('address_id')
        pay_method = json_dict.get('pay_method')

        # 2.校验(address_id  +  pay_method)
        if not all([address_id, pay_method]):
            return http.HttpResponseForbidden('缺少必传参数')

        try:
            address = Address.objects.get(id=address_id)
        except Address.DoesNotExist:
            return http.HttpResponseForbidden('address_id有误')

        if pay_method not in [OrderInfo.PAY_METHODS_ENUM['CASH'],
                              OrderInfo.PAY_METHODS_ENUM['ALIPAY']]:
            return http.HttpResponseForbidden('pay_method有误')

        user = request.user
        # 时间 + 用户id
        order_id = timezone.localtime().strftime('%Y%m%d%H%M%S') + ('%09d' % user.id)
        # 3.往OrderInfo表中增加数据

        with transaction.atomic():
            save_id = transaction.savepoint()
            try:
                order = OrderInfo.objects.create(
                    order_id=order_id,
                    user=user,
                    address=address,
                    total_count=0,
                    total_amount=Decimal('0.00'),
                    freight=Decimal('10.00'),
                    pay_method=pay_method,
                    status=OrderInfo.ORDER_STATUS_ENUM['UNPAID'] if pay_method == OrderInfo.PAY_METHODS_ENUM[
                        'ALIPAY'] else OrderInfo.ORDER_STATUS_ENUM['UNSEND']
                )

                #  4. 链接redis
                redis_conn = get_redis_connection('carts')

                # 5. 从hash取数据 {cart_user_id: {sku_id:count}}  --->  count
                item_dict = redis_conn.hgetall('carts_%s' % user.id)

                # 6. 从set 取数据 {selected_user_id : [sku_id1, ...]} ---->  sku_id
                cart_selected = redis_conn.smembers('selected_%s' % user.id)

                cart = {}
                # 7. 设置一个字典:  {sku_id: count}
                for sku_id in cart_selected:
                    cart[int(sku_id)] = int(item_dict[sku_id])

                # 8. 获取所有的set表中的sku_id
                sku_ids = cart.keys()

                # 9. 遍历: 拿取每一个
                for sku_id in sku_ids:

                    while True:
                        # 10. 根据sku_id 获取sku
                        sku = SKU.objects.get(id=sku_id)

                        # 11. 获取销售数量  sku.id == sku_id
                        sku_count = cart[sku.id]

                        origin_stock = sku.stock
                        origin_sales = sku.sales

                        # 12. 检验库存压力:
                        if sku_count > origin_stock:
                            transaction.savepoint_rollback(save_id)
                            return http.JsonResponse({'code': RETCODE.STOCKERR,
                                                      'errmsg': '库存不足'})

                        # import time
                        # time.sleep(5)

                        # 13. 修改对应商品的销量和库存量
                        # sku.stock -= sku_count
                        # sku.sales += sku_count
                        # sku.save()

                        new_stock = origin_stock - sku_count
                        new_sales = origin_sales + sku_count

                        result = SKU.objects.filter(id=sku_id,
                                                    stock=origin_stock).update(stock=new_stock, sales=new_sales)

                        if result == 0:
                            # 没有修改一个商品:
                            continue

                        # 14. 修改对应类别的销量
                        sku.goods.sales += sku_count
                        sku.goods.save()

                        # 15. 保存OrderGoods的数据(订单对应的所有的商品)
                        OrderGoods.objects.create(
                            order=order,
                            sku=sku,
                            count=sku_count,
                            price=sku.price
                        )

                        # 16.更新orderinfo表中的total_count + total_amount
                        order.total_count += sku_count
                        order.total_amount += (sku.price * sku_count)
                        break
            except Exception as e:
                transaction.savepoint_rollback(save_id)
                return http.JsonResponse({
                    'code': RETCODE.DBERR,
                    'errmsg': '下单失败'})
            transaction.savepoint_commit(save_id)

        # 17.total_amount增加运费
        order.total_amount += order.freight

        # 18.保存
        order.save()

        # 19.清空购物车中对应的这些商品
        redis_conn.hdel('carts_%s' % user.id, *cart_selected)
        redis_conn.srem('selected_%s' % user.id, *cart_selected)

        # 20.返回
        return http.JsonResponse({'code': RETCODE.OK,
                                  'errmsg': 'ok',
                                  'order_id': order.order_id})


class OrderSettlementView(LoginRequiredMinxin, View):

    def get(self,  request):
        '''
        返回订单页面
        :param request:
        :return:
        '''
        # 1.根据当前用户, 获取所有的没有删除的收货地址
        try:
            addresses = Address.objects.filter(user=request.user,
                                   is_deleted=False)
        except Address.DoesNotExist:
            addresses = None

        # 2.链接redis
        redis_conn = get_redis_connection('carts')

        # 3.获取hash值  {carts_user.id: {sku_id:count}}
        item_dict = redis_conn.hgetall('carts_%s' % request.user.id)

        # 4.获取set值  {selected_user.id: [sku_id1, sku_id2]}
        selected_cart = redis_conn.smembers('selected_%s' % request.user.id)

        dict = {}
        # 5.把set中的sku_id 和 hash中的count关联到一起
        for sku_id in selected_cart:
            dict[int(sku_id)] = int(item_dict[sku_id])

        # 6.准备初始化的值
        total_count = 0
        total_amount = Decimal('0.00')

        # 7.获取set中的所有对应商品
        skus = SKU.objects.filter(id__in=dict.keys())

        # 8.遍历商品, 增加连个count amount
        for sku in skus:
            sku.count = dict.get(sku.id)
            sku.amount = sku.price * sku.count

            # 9.累加
            total_count += sku.count
            total_amount += sku.amount

        # 10.定义运费
        freight = Decimal('10.00')

        # 11. 拼接参数
        context = {
            'addresses':addresses,
            'skus':skus,
            'total_count':total_count,
            'total_amount':total_amount,
            'freight':freight,
            'payment_amount':total_amount + freight
        }

        # 12. 返回
        return render(request, 'place_order.html', context)
